from PIL import Image
import math
from api.info.color_utils import *
from api import Startard_Info,STRATEGY


class TargetNode():
    def __init__(self,img,x1, y1, x2, y2,classify_models=None,init_color=True):
        self.box = (x1,y1,x2,y2)
        self.img = img
        self.classify_models = classify_models
        if init_color:
            self.center_rgb = self.get_image_center_rgb(img)
            self.side_rgb = self.get_image_side_rgb(img)
            self.hsv = rgb2hsv(*self.center_rgb)
        else:
            self.center_rgb = (0,0,0)
            self.side_rgb = (0,0,0)
        # self.camera_rgb = self.get_camera_color()
        # self.center_rgb = self.get_reduction_color()
        self.center_x = (x1 + x2) / 2
        self.center_y = (y1 + y1) / 2
        self.label = ""

        self.grade = ""
        self.color = ""
        self.value = ""

        self.standard_color = ""
        self.init_color = init_color

    def del_nosiy_pix(self,pixel_list):
        # 返回 RGB 值
        total_r = int(sum([i[0] for i in pixel_list]) / len(pixel_list))
        total_g = int(sum([i[1] for i in pixel_list]) / len(pixel_list))
        total_b = int(sum([i[2] for i in pixel_list]) / len(pixel_list))

        reduce_index = -1
        max_diff = 0
        for index, pix in enumerate(pixel_list):
            temp_diff = abs(total_r + total_g + total_b  - sum(pix))
            if temp_diff > max_diff:
                reduce_index = index

        del pixel_list[reduce_index]

    def get_image_center_rgb(self,img):
        width, height = img.size
        # 获取图片的中心坐标
        center_x = width // 2
        center_y = height // 2
        # 获取中心区域的像素
        pixel_list = [img.getpixel((center_x, center_y))]

        min_height = int(min(center_x *2/3,center_y * 2/3))
        cener_width  = int(min(center_x *1/6,center_y * 1/6))
        for i in range(cener_width, min_height):
            pixel_list.append(img.getpixel((center_x - i, center_y)))
            pixel_list.append(img.getpixel((center_x - i, center_y - i)))
            pixel_list.append(img.getpixel((center_x + i, center_y)))
            pixel_list.append(img.getpixel((center_x + i, center_y + i)))

        reduce_count = int(len(pixel_list) * 0.3)
        while reduce_count >0:
            self.del_nosiy_pix(pixel_list)
            reduce_count -= 1

        tupler_pixel_list = [tuple(i) for i in pixel_list]
        # from collections import Counter
        # o = Counter(tupler_pixel_list)
        # j = o.most_common(1)[0][0]
        #返回 RGB 值
        total_r = int(sum([i[0] for i in pixel_list]) / len(pixel_list))
        total_g = int(sum([i[1] for i in pixel_list]) / len(pixel_list))
        total_b = int(sum([i[2] for i in pixel_list]) / len(pixel_list))
        return (total_r, total_g, total_b)
        #return j


    def get_node_distance(self,otherNode):
        xDiff = self.center_x - otherNode.center_x
        yDiff = self.center_y - otherNode.center_y
        self.distiance =  math.sqrt(xDiff ** 2 + yDiff ** 2)


    def set_label(self,label):
        self.label = label


    def get_image_side_rgb(self,img):
        return img.getpixel((0, 0))


    def get_predict_info_yolo(self):
        if self.label in self.classify_models:
            predict = self.classify_models[self.label](self.img)[0]
            predict_label = predict.names[predict.probs.top1]


            if predict_label == 'ruoyang':
                self.grade = "+-"
                self.value = "4.6"
            elif predict_label == 'yang':
                self.grade = "+"
                self.value = "4.8"
            else:
                self.grade = "-"
                self.value = "4.4"


    def get_predict_info(self,user_type,use_fuc):
        if self.label != "":
            stard_class_info = Startard_Info[self.label]

            if user_type == "":
                user_type = STRATEGY[self.label]["use_type"]

            if use_fuc == "":
                use_fuc = STRATEGY[self.label]["use_fuc"]
            match_key = ""
            match_distince = 10000
            for key, value in stard_class_info.items():
                key_rgb = conver_str2rgb(key)
                key_distince = color_diff(self.center_rgb, key_rgb, user_type, use_fuc)
                if key_distince < match_distince:
                    match_distince = key_distince
                    match_key = key

            self.grade = stard_class_info[match_key]['grade']
            self.value = stard_class_info[match_key]['value']
            self.standard_color = "#" + match_key


            final_value = self.make_label_strategy(self.value, self.label)
            #
            # # self.color = match_key
            self.grade, self.standard_color = self.make_output_label_info(final_value, stard_class_info)
            self.value = final_value



    def get_join_result(self,user_type,use_fuc):
        self.get_predict_info(user_type,use_fuc)
        old_value,old_grade = str(self.value),self.grade

        self.get_predict_info_yolo()
        yolo_value,yolo_grade = self.value,self.grade

        final_value,final_grade = "",""
        if self.label in ["PH","H2O2"]:
            if yolo_value:
                if old_value == '4.1':
                    if yolo_value != "4.8":
                        final_value = old_value
                        final_grade = old_grade
                    else:
                        final_value = yolo_value
                        final_grade = yolo_grade
                elif old_value == '4.4':
                    if yolo_value == '4.6':
                        final_value = old_value
                        final_grade = old_grade
                    else:
                        final_value = yolo_value
                        final_grade = yolo_grade

                elif old_value == '5.1':
                    if yolo_value == '4.4' or yolo_value =="4.6":
                        final_value = yolo_value
                        final_grade = yolo_grade
                    else:
                        final_value = old_value
                        final_grade = old_grade
                else:
                    final_value = yolo_value
                    final_grade = yolo_grade
            else:
                final_value = old_value
                final_grade = old_grade
        else:
            if yolo_value:
                if old_value == '4.1':
                    if yolo_value == "4.4":
                        final_value = old_value
                        final_grade = old_grade
                    else:
                        final_value = yolo_value
                        final_grade = yolo_grade
                elif old_value == '5.1':
                    if yolo_value == '4.4':
                        final_value = yolo_value
                        final_grade = yolo_grade
                    else:
                        final_value = old_value
                        final_grade = old_grade
                else:
                    final_value = yolo_value
                    final_grade = yolo_grade
            else:
                final_value = old_value
                final_grade = old_grade




        self.grade = final_grade
        self.value = final_value





    def make_output_label_info(self,final_value,stard_class_info):
        '''根据value找到最终的输出label信息'''
        for key,info in stard_class_info.items():
            if info["value"] == final_value:
                return info["grade"],key
        else:
            return "",""


    def make_label_strategy(self,value,label):
        '''
        根据不同指标结果，生成最终label
        :param result:
        :param label:
        :return:
        '''
        if label == "H2O2":
            if value  == 4.6:
                if self.hsv[0] >= 0 and self.hsv[0] <= 60:
                    value = 4.8
                elif self.hsv[0] >= 110 and self.hsv[1] >= 15 and self.hsv[1] <= 30:
                    value = 4.4
            elif value == 4.4:
                if self.hsv[1] >= 15 and self.hsv[1] <= 30:
                    value = 4.4
                else:
                    value = 4.6
            elif value == 4.8:
                if self.hsv[0] >= 0 and self.hsv[0] <= 60:
                    value = 4.8
                else:
                    value = 4.6
        elif label == 'PH':
            if value == 4.6:
                if self.hsv[0] >70 :
                    value = 4.8
            elif value == 4.8:
                if self.hsv[0] <= 70:
                    value = 4.6
        elif label == "OA":
            if value == 4.6:
                if self.hsv[1]<=8:
                    value = 4.4
        elif label == "SNA":
            if value == 4.4 or  value == 4.1:
                if self.hsv[0] >= 80 and self.hsv[1] >= 4:
                    value = 4.6
        elif label == "NAG":
            if value == 4.4:
                if  self.hsv[1] >= 9  and ( self.hsv[0] <= 25 or self.hsv[0] >=61):
                    value = 4.6
                # elif (self.hsv[0] >= 20 and self.hsv[0] <= 61) and self.hsv[1] >= 9 and self.hsv[2]<=81:
                #     value = 4.6
            elif value == 4.6 or value == 4.8 or value == 5.1:
                if self.hsv[1] <=3:
                    value = 4.4
        elif label == "PIP":
            if value == 4.6:
                if self.hsv[1] <= 15:
                    value = 4.4
        return value








    def to_json(self):
        return {self.label:{"color":self.color,
                "value":self.value,
                "grade":self.grade,
                "standard_color":self.standard_color,
                "hsv_color":self.hsv,
                "center_color":rgb_to_hex(self.center_rgb).upper(),
                "side_color":rgb_to_hex(self.side_rgb).upper(),
                "box":self.box}
                }


    def get_camera_color(self):
        return (self.side_rgb[0]*2 -255,self.side_rgb[1]*2 - 255,self.side_rgb[2]*2 - 255)

    def get_reduction_color(self):


        return (self.center_rgb[0]*2 - self.camera_rgb[0],self.center_rgb[1]*2 - self.camera_rgb[1],self.center_rgb[2]* 2 - self.camera_rgb[2])